#ifndef __S264_NALU_H__
#define __S264_NALU_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include "impl.h"
#include "bs.h"
	
	typedef struct nalu_st {
		u8 startcode_len;
		u8 *buf;
		u64 buf_len;
	}nalu_t;

	extern i8 nalu_rbsp(u8 *nostartcode_buf, u64 nostartcode_buf_len, s264buf_t *rbsp_buf);
	
// forbidden_bit(1) 编码中默认值为0, 当网络识别此单元中存在比特错误时, 可将其设为1, 以便接收方丢掉该单元
#define nalu_forbidden_bit(c) (((c) >> 7) &1)
// nal_ref_idc(3) 0~3标识这个NALU的重要级别
#define nalu_nal_ref_idc(c) (((c) >> 5) & 3)
// nal_unit_type(5)  NALU的类型(类型1~12是H.264定义的, 类型24~31是用于H.264以外的 RTP负荷规范使用这其中的一些值来定义包聚合和分裂, 其他值为H.264保留)
#define nalu_nal_unit_type(c) ((c >> 0) & 0x1f)
	/*
	nal_unit_type:
		0                未使用
		1                未使用Data Partitioning, 非IDR图像的Slice (I Slice)
		2                使用Data Partitioning且为Slice A
		3                使用Data Partitioning且为Slice B
		4                使用Data Partitioning且为Slice C
		5                IDR图像的Slice(立即刷新)
		6                补充增强信息(SEI) 放弹幕，编码器信息...
		7                序列参数集(sequence parameter set, SPS)
		8                图像参数集(picture parameter set, PPS)
		9                分界符
		10                序列结束
		11                码流结束
		12                填充
		13...23            保留
		24...31            未使用
	*/
	enum {
		nalu_ref_idc_disposable = 0,
		nalu_ref_idc_low = 1,
		nalu_ref_idc_high = 2,
		nalu_ref_idc_highset = 3,
	};

	enum {
		nalu_type_slice = 1,
		nalu_type_dpa = 2,
		nalu_type_dpb = 3,
		nalu_type_dbc = 4,
		nalu_type_idr = 5,
		nalu_type_sei = 6,
		nalu_type_sps = 7,
		nalu_type_pps = 8,
		nalu_type_aud = 9,
		nalu_type_eoseq = 10,
		nalu_type_eostream = 11,
		nalu_type_fill = 12,
	};

	typedef struct nalu_hrd_st
	{
		u64 cpb_cnt_minus1;
		u8 bit_rate_scale : 4, cpb_size_scale : 4;
		u64 *bit_rate_value_minus1;
		u64 *cpb_size_value_minus1;
		u8 *cbr_flag;
		u32 initial_cpb_removal_delay_length_minus1 : 5,
			cpb_removal_delay_length_minus1 : 5,
			dpb_output_delay_length_minus1 : 5,
			time_offset_length : 5;
	}nalu_hrd_t;


	typedef struct nalu_vui_st
	{
		// flags
		u16 aspect_ratio_info_present_flag : 1,
			overscan_info_present_flag : 1,
			overscan_appropriate_flag : 1,
			video_signal_type_present_flag : 1,
			video_full_range_flag : 1,
			colour_description_present_flag : 1,
			chroma_loc_info_present_flag : 1,
			timing_info_present_flag : 1,
			fixed_frame_rate_flag : 1,
			nal_hrd_parameters_present_flag : 1,
			vcl_hrd_parameters_present_flag : 1,
			low_delay_hrd_flag : 1,
			pic_struct_present_flag : 1,
			bitstream_restriction_flag : 1,
			motion_vectors_over_pic_boundaries_flag : 1;
		u8 aspect_ratio_idc;
		u16 sar_width;
		u16 sar_height;
		u8 video_format;
		u8 colour_primaries;
		u8 transfer_characteristics;
		u8 matrix_coefficients;
		u64 chroma_sample_loc_type_top_field;
		u64 chroma_sample_loc_type_bottom_field;
		u32 num_units_in_tick;
		u32 time_scale;
		u64 max_bytes_per_pic_denom;
		u64 max_bits_per_mb_denom;
		u64 log2_max_mv_length_horizontal;
		u64 log2_max_mv_length_vertical;
		u64 num_reorder_frames;
		u64 max_dec_frame_buffering;
		nalu_hrd_t hrd1;
		nalu_hrd_t hrd2;
	}nalu_vui_t;

	

	typedef struct nalu_sps_st
	{
		u8 profile_idc;
		u8 constraint_set0_flag : 1,
			constraint_set1_flag : 1,
			constraint_set2_flag : 1,
			constraint_set3_flag : 1,
			reserved_zero_4bits : 4;
		u8 level_idc;
		u64 seq_parameter_set_id;
		u64 chroma_format_idc;
		u16 residual_colour_transform_flag : 1,
			qpprime_y_zero_transform_bypass_flag : 1,
			seq_scaling_matrix_present_flag : 1,
			delta_pic_order_always_zero_flag : 1,
			gaps_in_frame_num_value_allowed_flag : 1,
			frame_mbs_only_flag : 1,
			mb_adaptive_frame_field_flag : 1,
			direct_8x8_inference_flag : 1,
			frame_cropping_flag : 1,
			vui_parameters_present_flag:1;
		u64 bit_depth_luma_minus8;
		u64 bit_depth_chroma_minus8;
		u8 seq_scaling_list_present_flag[8];
		u64 log2_max_frame_num_minus4;
		u64 pic_order_cnt_type;
		u64 log2_max_pic_order_cnt_lsb_minus4;
		i64 offset_for_non_ref_pic;
		i64 offset_for_top_to_bottom_field;
		u64 num_ref_frames_in_pic_order_cnt_cycle;
		i64 *offset_for_ref_frame;
		u64 num_ref_frames;
		u64 pic_width_in_mbs_minus1;
		u64 pic_height_in_map_units_minus1;
		u64 frame_crop_left_offset;
		u64 frame_crop_right_offset;
		u64 frame_crop_top_offset;
		u64 frame_crop_bottom_offset;
		nalu_vui_t vui;
	}nalu_sps_t;


	typedef struct nalu_pps_st
	{

	}nalu_pps_t;

	extern void *nalu_parse(nalu_t *nalu, u8 *type);
	extern nalu_sps_t *nalu_parse_sps(bs_t *bs);
	extern nalu_pps_t *nalu_parse_pps(bs_t *bs);
	extern void nalu_deinit(void *ptr, u8 type);
#ifdef __cplusplus
}
#endif

#endif